/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#include "lua_engine.h"
extern "C"
{
#include "node-binding/lua/lualib.h"
#include "node-binding/lua/lauxlib.h"
}
#include "node-binding/tolua/tolua++.h"

#include "node-binding/auto/binding_sys.h"
#include "node-binding/auto/binding_util.h"
#include "node-binding/manual/binding_http.h"
#include "node/sys/console.h"
using Console = ::node::sys::Console;

namespace node_binding  {

    LuaEngine::LuaEngine(int init_modules /*= NMOD_SYS*/)
        : lua_state_(NULL)
        , mod_load_mask_(0)
    {
        if ((lua_state_ = lua_open()) == NULL) {
            Console::Error("%s, %d, lua_open failed\n", 
                __FILE__, __LINE__);
        }

        luaL_openlibs(lua_state_);
        LoadModules(init_modules);
    }

    LuaEngine::~LuaEngine(void)
    {
        if (lua_state_ != NULL) {
            lua_close(lua_state_);
        }
    }

    void LuaEngine::LoadModules(int modules)
    {
        if ((modules & NodeModule::NMOD_SYS) 
            && !(mod_load_mask_ & NodeModule::NMOD_SYS)) {
            LoadModule("node.sys", tolua_sys_open);
            mod_load_mask_ |= NodeModule::NMOD_SYS;
        }
        if ((modules & NodeModule::NMOD_UTIL)
            && !(mod_load_mask_ & NodeModule::NMOD_UTIL)) {
            LoadModule("node.util", tolua_util_open);
            mod_load_mask_ |= NodeModule::NMOD_UTIL;
        }
        if ((modules & NodeModule::NMOD_HTTP)
            && !(mod_load_mask_ & NodeModule::NMOD_HTTP)) {
            LoadModule("node.http", tolua_http_open);
            mod_load_mask_ |= NodeModule::NMOD_HTTP;
        }
    }

    void LuaEngine::DoFile(const char *filename)
    {
        int eno = luaL_loadfile(lua_state_, filename);
        if (eno == 0) {
            if ((eno = lua_pcall(lua_state_, 0, LUA_MULTRET, 0)) != 0) {
                Console::Warning("[LuaEngine::DoFile] lua_pcall %s failed, %d, %s\n",
                    filename, eno, lua_tostring(lua_state_, -1));
            }
            return;
        }
        Console::Warning("[LuaEngine::DoFile] luaL_loadfile %s failed, %d, %s\n",
            filename, eno, lua_tostring(lua_state_, -1));
    }

    void LuaEngine::LoadModule(const char *name, TOLUA_MODULE_OPEN fn)
    {
        int eno = fn(lua_state_);
        if (eno != 1) {
            Console::Warning("[LuaEngine::LoadModule] load %s failed, %d, %s\n",
                name, eno, lua_tostring(lua_state_, -1));
        }
    }
}